package com.nx.adaper.shopify.schedule;

import cn.hutool.core.thread.ThreadUtil;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.nx.biz.shopify.api.bo.ShopifyFulfillment;
import com.nx.biz.shopify.api.bo.ShopifyOrder;
import com.nx.biz.shopify.convert.ShopifyFulfillmentConverter;
import com.nx.biz.shopify.convert.ShopifyOrderConverter;
import com.nx.biz.shopify.mapper.ShopifyFulfillmentMapper;
import com.nx.biz.shopify.mapper.ShopifyOrderMapper;
import com.nx.biz.shopify.model.ShopifyFulfillmentDo;
import com.nx.biz.shopify.model.ShopifyOrderDo;
import com.nx.biz.shopify.repo.ShopifyFulfillmentRepository;
import com.nx.biz.shopify.repo.ShopifyOrderRepository;
import com.nx.biz.shopify.sdk.ShopifySdk.model.constant.ShipmentStatusConstants;
import com.nx.biz.shopify.service.TrackSyncService;
import com.nx.common.tools.CheckTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.shaded.com.google.common.collect.Lists;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据同步调度器
 */
@Slf4j
@Component
public class DataSyncScheduler {

    @Resource
    private ShopifyOrderRepository shopifyOrderRepository;
    @Resource
    private ShopifyFulfillmentRepository shopifyFulfillmentRepository;

    @Resource
    private ShopifyFulfillmentMapper shopifyFulfillmentMapper;
    @Resource
    private ShopifyOrderMapper shopifyOrderMapper;
    @Resource
    private ShopifyFulfillmentConverter shopifyFulfillmentConverter;
    @Resource
    private ShopifyOrderConverter shopifyOrderConverter;

    @Resource
    private TrackSyncService trackSyncService;

    /**
     * shopify order的状态会根据回调，动态的更新，所以他的状态可以作为更新快递单号的依据
     */
    public List<ShopifyOrder> listToSyncTrackNumber() {
        MPJLambdaWrapper<ShopifyOrderDo> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper
                .select(ShopifyOrderDo::getId)
                .select(ShopifyOrderDo::getAdminGraphqlApiId)
                .select(ShopifyOrderDo::getName)
                .select(ShopifyOrderDo::getShopDomain)
                .select(ShopifyOrderDo::getTrackNumber)
                .select(ShopifyOrderDo::getFinancialStatus)
                .select(ShopifyOrderDo::getFulfillmentStatus)
                .select(ShopifyOrderDo::getTotalLineItemsPrice)
                .select(ShopifyOrderDo::getTotalPrice)
                .select(ShopifyOrderDo::getOrderStatusUrl)
                .leftJoin(ShopifyFulfillmentDo.class,ShopifyFulfillmentDo::getOrderId,ShopifyOrderDo::getId)
                // 存在fulfillment
                .isNotNull(ShopifyFulfillmentDo::getId)
                // 并且fulfillment没有配送完成
                .ne(ShopifyFulfillmentDo::getShipmentStatus,ShipmentStatusConstants.delivered);

        List<ShopifyOrderDo> shopifyOrderDos = shopifyOrderMapper.selectList(queryWrapper);
        if (CheckTools.isNotNullOrEmpty(shopifyOrderDos)) {
            return shopifyOrderConverter.toBoList(shopifyOrderDos);
        }
        return new ArrayList<>();
    }

    public List<ShopifyFulfillment> listToSyncTrackInfo() {
        /** 未运输完成的订单（shipment status非完成状态的) */

        MPJLambdaWrapper<ShopifyFulfillmentDo> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper
                .select(ShopifyFulfillmentDo::getId)
                .select(ShopifyFulfillmentDo::getAdminGraphqlApiId)
                .select(ShopifyFulfillmentDo::getName)
                .select(ShopifyFulfillmentDo::getShopId)
                .select(ShopifyFulfillmentDo::getShopDomain)
                .select(ShopifyFulfillmentDo::getOrderId)
                .select(ShopifyFulfillmentDo::getFulfillmentOrderId)
                .select(ShopifyFulfillmentDo::getStatus)
                .select(ShopifyFulfillmentDo::getShipmentStatus)
                .select(ShopifyFulfillmentDo::getService)
                .select(ShopifyFulfillmentDo::getLocationId)
                .select(ShopifyFulfillmentDo::getEmail)
                .select(ShopifyFulfillmentDo::getTrackingCompany)
                .select(ShopifyFulfillmentDo::getTrackingNumber)
                .select(ShopifyFulfillmentDo::getTrackingUrl)
                .select(ShopifyFulfillmentDo::getDestination)
                .select(ShopifyFulfillmentDo::getItems)
                .select(ShopifyFulfillmentDo::getCreateAt)
                .select(ShopifyFulfillmentDo::getUpdateAt)
                .leftJoin(ShopifyOrderDo.class,ShopifyOrderDo::getId,ShopifyFulfillmentDo::getOrderId)
                .isNotNull(ShopifyOrderDo::getTrackNumber)
                .and(subWrapper -> {
                    subWrapper.isNull(ShopifyFulfillmentDo::getShipmentStatus).or()
                            .ne(ShopifyFulfillmentDo::getShipmentStatus,ShipmentStatusConstants.delivered);
                });

        List<ShopifyFulfillmentDo> shopifyFulfillmentDos = shopifyFulfillmentMapper.selectList(queryWrapper);
        if (CheckTools.isNotNullOrEmpty(shopifyFulfillmentDos)) {
            return shopifyFulfillmentConverter.toBoList(shopifyFulfillmentDos);
        }
        return new ArrayList<>();
    }

    /**
     * 定时同步运单
     */
    @Scheduled(cron = "0/45 * * * * ?")
    public void syncTrackNumberFromErp() {
        log.info("");
        log.info("");
        log.info("====================================== 定时任务-运单同步-[start] ======================================");
        // 从db查询没有快递单号的order （shopify order需要同步保存）
        List<ShopifyOrder> shopifyOrderEoList = listToSyncTrackNumber();
        if (CheckTools.isNullOrEmpty(shopifyOrderEoList)) {
            log.info("没有订单需要同步track number");
            log.info("====================================== 定时任务-运单同步-[cancel] ======================================");
            return;
        }
        log.info("共 {} 个订单需要同步track number", shopifyOrderEoList.size());
        // 分段 向货代erp查询这些订单的快递单号
        List<List<ShopifyOrder>> groupList = Lists.partition(shopifyOrderEoList, 100);
        for (List<ShopifyOrder> subList : groupList) {
            trackSyncService.syncTrackNumber(subList);
            //时间间隔为1秒1次（华磊是1秒5次)
            ThreadUtil.sleep(500);
        }
        log.info("====================================== 定时任务-运单同步-[end] ======================================");
    }

    /**
     * 定时同步运踪
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void syncTrackInfoFromErp() {
        log.info("");
        log.info("");
        log.info("====================================== 定时任务-运踪同步-[start] ======================================");
        // 从db查询有快递单号，但是未完成的 order
        List<ShopifyFulfillment> shopifyFulfillmentEoList = listToSyncTrackInfo();
        if (CheckTools.isNullOrEmpty(shopifyFulfillmentEoList)) {
            log.info("没有订单需要同步track info");
            log.info("====================================== 定时任务-运踪同步-[cancel] ======================================");
            return;
        }
        log.info("共 {} 个fulfillment需要同步track info", shopifyFulfillmentEoList.size());

        // 分段 向货代erp查询这些订单运踪
        List<List<ShopifyFulfillment>> groupList = Lists.partition(shopifyFulfillmentEoList, 100);
        for (List<ShopifyFulfillment> subList : groupList) {
            trackSyncService.syncTrackEvent(subList);
            //时间间隔为1秒1次（华磊是1秒5次)
            ThreadUtil.sleep(500);
        }
        log.info("====================================== 定时任务-运踪同步-[end] ======================================");
    }

}
